import net.sf.javaml.classification.AbstractClassifier;
import net.sf.javaml.core.Dataset;
import net.sf.javaml.core.DefaultDataset;
import net.sf.javaml.core.Instance;

import java.util.HashMap;

/**
 * Naive Bayesian classifier.
 * @author Jan Schagerstr�m
 */

public class NaiveBayes extends AbstractClassifier {

	private DataSet data;
	private int vectorLength = 200;	//length of the vectors		
	private HashMap<Object, double[]> probabilities; 
	
	public NaiveBayes() {
	
	}
	public NaiveBayes(int vectorLength) {
		this.vectorLength = vectorLength;
	}
	public NaiveBayes(Dataset data) {
		buildClassifier(data);
	}
	
	@Override
	public void buildClassifier(Dataset data) {
		this.data = new DataSet(data);
		probabilities = new HashMap<Object, double[]>();
		
		int sum = 0;

		for (Object currentClass : data.classes()) {
		
         int numOfDocs = 0;
         for(Instance ci : data) {
	         if (ci.classValue().equals(currentClass))
 	           numOfDocs++;
	      }
			double[] classProbs = new double[vectorLength];
			for (int i = 0; i < vectorLength; i++) {
   	      sum = 0;
	         for(Instance ci : data) {
    	        if (ci.classValue().equals(currentClass)) {
					  if (ci.value(i) > 0) {
  	    	          sum += 1;
                 }
              }
            }
				double termCategory = ((double) sum) / (double) numOfDocs;
				classProbs[i] = termCategory;
			}
			probabilities.put(currentClass, classProbs);
		}

	} 
	
	@Override
	public Object classify (Instance instance) {
		double probability     = 1;
		boolean changed        = false;	
		double currentMax      = 0;
		Object currentMaxClass = "Default";

		for (Object currentClass : data.classes()) {
		
    		changed = false;        
         probability = 1;
			double[] classProbs = probabilities.get(currentClass);
			for (int i = 0; i < vectorLength; i++) {
				double termInstance = instance.value(i);
				if (termInstance > 0){
	    			changed = true;        
					probability += classProbs[i];
				}
			}
			if ((probability >= currentMax) && changed) {
				currentMax = probability;
				currentMaxClass = currentClass;
			}
		}
		return currentMaxClass;
	}

}